home *** CD-ROM | disk | FTP | other *** search
- /* Handles body/head/manipulator mappings */
-
- /* Written by Dave Stampe, August 1992 */
-
- // modified for VRC for better viewpoint control
- // and default body ssegment access
-
- // Split up, rearranged, parially ported to VR-3866 API
-
- /*
- This code is part of the VR-386 project, created by Dave Stampe.
- VR-386 is a desendent of REND386, created by Dave Stampe and
- Bernie Roehl. Almost all the code has been rewritten by Dave
- Stampre for VR-386.
-
- Copyright (c) 1994 by Dave Stampe:
- May be freely used to write software for release into the public domain
- or for educational use; all commercial endeavours MUST contact Dave Stampe
- (dstampe@psych.toronto.edu) for permission to incorporate any part of
- this software or source code into their products! Usually there is no
- charge for under 50-100 items for low-cost or shareware products, and terms
- are reasonable. Any royalties are used for development, so equipment is
- often acceptable payment.
-
- ATTRIBUTION: If you use any part of this source code or the libraries
- in your projects, you must give attribution to VR-386 and Dave Stampe,
- and any other authors in your documentation, source code, and at startup
- of your program. Let's keep the freeware ball rolling!
-
- DEVELOPMENT: VR-386 is a effort to develop the process started by
- REND386, improving programmer access by rewriting the code and supplying
- a standard API. If you write improvements, add new functions rather
- than rewriting current functions. This will make it possible to
- include you improved code in the next API release. YOU can help advance
- VR-386. Comments on the API are welcome.
-
- CONTACT: dstampe@psych.toronto.edu
- */
-
-
- #include <stdio.h>
- #include <stdlib.h> /* atexit() */
- #include <mem.h> /* memcpy() */
- #include <dos.h>
-
- #include "pointer.h"
- #include "vr_api.h"
- #include "segment.h"
- #include "intmath.h"
- #include "splits.h"
- #include "pcdevice.h"
-
-
-
- /************* SIMPLE 3D/6D OBJECT MANIPULATION *********/
-
- static OBJECT *sel_obj;
- static SEGMENT *work_seg;
- static SEGMENT *old_parent;
-
- static SEGMENT *rot_seg = NULL; /* used to rotate objects by center */
-
- static MATRIX ogm;
- static long oxp, oyp, ozp;
- static long oxg, oyg, ozg;
-
- #define FREE_DO 0 // released
- #define GRASP_DO 1 // holding
- #define ROTATE_DO 2 // "pinch" rotation emulation for 3D dev.
- #define SELECT_DO 3 // looking for an object to grasp...
-
- static gmode = FREE_DO; // current grasping mode
-
-
- //// STILL USES SEGMENT CALLS FOR NOW
-
- static PDRIVER *manip_pdriver = NULL;
- static SEGMENT *manip_segment = NULL;
- static SEGMENT *manip_sel_seg = NULL;
- static POSE manip_sel_offset = ZERO_POSE;
-
-
- // sets up the 3D/6D manip system
- void set_3D_manip_data(PDRIVER *ptr, SEGMENT *move, SEGMENT *sel, POSE *seloffset)
- {
- manip_pdriver = ptr;
- manip_segment = move;
- manip_sel_seg = sel;
- manip_sel_offset = *seloffset;
- }
-
-
- static SEGMENT *manip_data(long *x, long *y, long *z)
- {
- *x = manip_sel_offset.x;
- *y = manip_sel_offset.y;
- *z = manip_sel_offset.z;
- matrix_point(*get_seg_pmatrix(manip_sel_seg), x, y, z);
-
- return manip_segment;
- }
-
-
-
- void do_3D_manip(WORD command) /* glove execution loop element */
- {
- OBJLIST *list;
- OBJECT * obj;
- int s;
- long d,x,y,z;
- MATRIX f;
- MATRIX *m;
-
- POINTER pt;
- SEGMENT *wrist_seg = manip_data(&x, &y, &z); // local manipulation
- // very general call
- if (manip_pdriver==NULL) return;
- if (!rot_seg) rot_seg = new_seg(NULL); // initialize if needed
-
- s = last_pointer(manip_pdriver, &pt);
-
- newmode:
- switch(gmode)
- {
- case FREE_DO:
- switch(command)
- {
- case SELECT_DO:
- gmode = SELECT_DO;
- do_for_all_selected(unhighlight_object);
- sel_obj = NULL;
- world_changed++;
- goto newmode;
- case GRASP_DO:
- if (sel_obj)
- {
- work_seg = object2segment(sel_obj);
- old_parent = parent_segment(work_seg);
- if (old_parent) detach_segment(work_seg,1);
- attach_segment(work_seg, wrist_seg,1);
- gmode = GRASP_DO;
- world_changed++;
- }
- break;
- case ROTATE_DO:
- if (sel_obj)
- {
- work_seg = object2segment(sel_obj);
- if (work_seg == NULL) break;
- old_parent = parent_segment(work_seg);
- update_segment(work_seg);
- if (old_parent == NULL)
- get_object_bounds(sel_obj, &oxp, &oyp, &ozp); /* center of obj */
- else
- {
- m = get_seg_pmatrix(work_seg); /* else by origin ("joint") */
- oxp = (*m)[3][0];
- oyp = (*m)[3][1];
- ozp = (*m)[3][2];
- }
- abs_rot_segment(rot_seg, 0, 0, 0, RYXZ);
- abs_move_segment(rot_seg, oxp, oyp, ozp);
- update_segment(rot_seg);
- attach_segment(work_seg, rot_seg,1);
- oxg = x-oxp;
- oyg = y-oyp;
- ozg = z-ozp;
- vector_to_matrix(f, oxg, oyg, ozg);
- inverse_matrix(f, ogm);
- gmode = ROTATE_DO;
- world_changed++;
- }
- break;
- default:
- break;
- }
- break;
- case SELECT_DO:
- switch(command)
- {
- case SELECT_DO:
- list = which_area_objlist(global_world_root, x, y, z);
- if (list != NULL)
- {
- obj = best_collision(list, x, y, z);
- if (obj == NULL)
- {
- unhighlight_object(sel_obj);
- sel_obj = NULL;
- }
- else
- {
- if (sel_obj != obj) unhighlight_object(sel_obj);
- highlight_object(obj);
- sel_obj = obj;
- }
- world_changed++;
- }
- break;
- default:
- gmode = FREE_DO;
- goto newmode;
- }
- break;
- case GRASP_DO:
- switch(command)
- {
- case GRASP_DO:
- break; /* move is automatic */
- default:
- if (work_seg)
- {
- detach_segment(work_seg,1);
- if (old_parent) attach_segment(work_seg, old_parent,1);
- world_changed++;
- }
- gmode = FREE_DO;
- goto newmode;
- }
- break;
- case ROTATE_DO:
- switch(command)
- {
- case ROTATE_DO:
- if (sel_obj && (s & PNEW_POS))
- {
- vector_to_matrix(f, x-oxp, y-oyp, z-ozp);
- matrix_product(f, ogm, f);
- f[3][0] = oxp;
- f[3][1] = oyp;
- f[3][2] = ozp;
- abs_mat_segment(rot_seg, f);
- update_segment(rot_seg);
- world_changed++;
- }
- break;
- default:
- gmode = FREE_DO;
- world_changed++;
- detach_segment(work_seg,1);
- if (old_parent) attach_segment(work_seg, old_parent,1);
- goto newmode;
- }
- break;
- default:
- break;
- }
- }
-
-
-